home *** CD-ROM | disk | FTP | other *** search
/ Megarom / Megarom Macintosh CD Software (Quantum Leap)(1992).iso / COMMUNICATION / BBS Software Systems / BBS-0.60 / simple < prev    next >
Text File  |  1990-05-30  |  29KB  |  1,619 lines

  1. /*
  2.  *    Copyright © 1990 Paul Campbell, Taniwha Systems Design
  3.  *    All Rights Reserved.
  4.  *    Right to redistribute this software with the Taniwha BBS
  5.  *  is hereby granted.
  6.  */
  7.  
  8. const    NULL = 0,                /* nil pointer */
  9.         USERNLEN = 30,            /* length of a user name */
  10.         TIMEOUT = 7200,            /* timeout - 2 minutes - set to -1 to disable */
  11.         MAPSIZE = 128;            /* limit to the # lines in an edited file */
  12.  
  13. global     UserRecord[40],         /* user record from user file */
  14.         User[USERNLEN],            /* user name */
  15.         Directory[256],            /* directory name of root directory for BBS system */
  16.         Tmp[128],                /* temporary array */
  17.         Tmp1[128],                /* temporary array */
  18.         Tmp2[128],                /* temporary array */
  19.         TmpName[64],            /* temporary file name */
  20.         XUser[USERNLEN],         /* other user name (used for destination of mail etc) */
  21.         MailHdr[128],             /* mail file header record */
  22.         Subject[128],             /* mail subject */
  23.         nextc,                     /* next input char from edit_command() */
  24.         col,                     /* editor screen column */
  25.         line,                     /* editor screen line */
  26.         lineoffset,                /* index into screen of the start of the current line */
  27.         lcount,                 /* editor line count */
  28.         pos,                    /* editor line position */
  29.         efree,                    /* editor next free block */
  30.         elist,                    /* first in free edit block list */
  31.         lmod[23],                /* line has been modified */
  32.         screen[1840],             /* current screen being edited */
  33.         ftmp,                    /* temp file we have open */
  34.         fedit,                    /* temp file we have open for editing */
  35.         fuser,                    /* user file we have open */
  36.         MailState[6],            /* mail control file */
  37.         sysop,                    /* true if we are 'sysop' */
  38.         timeout,                /* system wide timeout */
  39.         Map[MAPSIZE];            /* edit file map */
  40.  
  41. /*
  42.  *        system-wide global variable use:
  43.  *
  44.  *            A - unique number, incremented on each use
  45.  *
  46.  *        system-wide lock uses
  47.  *
  48.  *            0 - user file
  49.  *            1 - lock on mail system
  50.  */
  51.  
  52. "simple"
  53. {
  54.     if (gettype() == 0) {
  55.         timeout = -1;
  56.     } else {
  57.         timeout = TIMEOUT;        /* set to -1 for no timeout */
  58.     }
  59.     for (;;) {
  60.         setuser("");
  61.         sysop = 0;
  62.         getdirectory(Directory);
  63.         setstate("Idle");
  64.         if (!enabled())
  65.             quit();
  66.         connect();
  67.         setstate("Login");
  68.         if (!login()) {
  69.             disconnect();
  70.             continue;
  71.         }
  72.         setstate("Active");
  73.         message_of_the_day();
  74.         setuser(User);
  75.         commands();
  76.         disconnect();
  77.         resched();            /* These recheds required for the CommToolbox to get the port back */
  78.         resched();            /* into a sane state before trying to connect again - no one knows why :-)*/
  79.         resched();
  80.     }
  81. }
  82.  
  83. do_hangup()
  84. {
  85.     setuser("");
  86.     if (TmpName[0]) {
  87.         remove(TmpName);
  88.         TmpName[0] = 0;
  89.     }
  90.     restart();
  91. }
  92.  
  93. commands()
  94. {
  95.     local c, j;
  96.     
  97.     for (;;) {
  98.         stty('e', 0);
  99.         stty('l', 0);
  100.         if (sysop) {
  101.             j = "C(onfig) ";
  102.         } else {
  103.             j = "";
  104.         }
  105.         printf("Main: %sP(assword) R(ead mail) S(end mail) F(iles) L(ogout) > ", j);
  106.         c = getchartime(timeout);
  107.         stty('e', 1);
  108.         stty('l', 1);
  109.         if (c == -2) {
  110.             return;
  111.         }
  112.         putchar(c);
  113.         putchar('\n');
  114.         switch(c) {
  115.         case 'P':
  116.         case 'p':
  117.             set_password(User, 0);
  118.             break;
  119.             
  120.         case 'C':
  121.         case 'c':
  122.             if (sysop)
  123.                 config();
  124.             break;
  125.             
  126.         case 'F':
  127.         case 'f':
  128.             do_files();
  129.             break;
  130.             
  131.         case 'R':
  132.         case 'r':
  133.             rmail();
  134.             break;
  135.             
  136.         case 'S':
  137.         case 's':
  138.             smail(0, 0, 0);
  139.             break;
  140.             
  141.         case 'L':
  142.         case 'l':    
  143.             return;
  144.         }
  145.     }
  146. }
  147.  
  148. /*
  149.  *    rmail searches for mail to the user
  150.  *        by looking in the subdirectory 'mail:USER'
  151.  */
  152.  
  153. rmail()
  154. {
  155.     local i, first, last, this, mod, c, done, x;
  156.     
  157.     i = get_mailstate(User, 0);
  158.     if (i < 0) {
  159.         printf("Mail Problem\n");
  160.         return;
  161.     }
  162.     first = (MailState[0]<<8)|MailState[1];
  163.     last  = (MailState[2]<<8)|MailState[3];
  164.     this  = (MailState[4]<<8)|MailState[5];
  165.     if (i == 0 || first > last) {
  166.         printf("No Mail\n");
  167.         return;
  168.     }
  169.     mod = 0;
  170.     printf("First message %d, Last Message %d, Current Message %d\n",
  171.                     first, last, this);
  172.     for (done = 0;!done;) {
  173.         stty('e', 0);
  174.         stty('l', 0);
  175.         printf("Mail(%d): A(ll) D(el) R(eply) H(eader) L(ist) T(his) Q(uit) +/-> ", this);
  176.         c = getchartime(timeout);
  177.         stty('e', 1);
  178.         stty('l', 1);
  179.         if (c == -2)
  180.             break;
  181.         putchar(c);
  182.         putchar('\n');
  183.         x = 0;
  184.         switch(c) {
  185.         case '-':
  186.             x = 1;
  187.             if (this > first) {
  188.                 mod = 1;
  189.                 this--;
  190.             }
  191.         case '\n':
  192.         case '\r':
  193.         case '+':
  194.             if (x == 0 && this < last) {
  195.                 mod = 1;
  196.                 this++;
  197.             }
  198.         case 'T':
  199.         case 't':
  200.             display_mail(this);
  201.             break;
  202.             
  203.         case 'r':
  204.         case 'R':
  205.             reply_mail(this);
  206.             break;
  207.             
  208.         case 'D':
  209.         case 'd':
  210.             mod = 1;
  211.             first = delete_mail(first, this, last);
  212.             break;
  213.             
  214.         case 'L':
  215.         case 'l':
  216.             pr_subjects(this, last);
  217.             break;
  218.             
  219.         case 'A':
  220.         case 'a':
  221.             pr_subjects(first, last);
  222.             break;
  223.             
  224.         case 'Q':
  225.         case 'q':    
  226.             done = 1;
  227.             break;
  228.         }
  229.     }
  230.     if (mod && get_mailstate(User, 1) == 1) {
  231.         MailState[0] = first>>8;
  232.         MailState[1] = first;
  233.         MailState[4] = this>>8;
  234.         MailState[5] = this;
  235.         set_mailstate(User, 1);
  236.     }
  237. }
  238.  
  239. /*
  240.  *    control file contains:
  241.  *
  242.  *    bytes     0-1        first mail message
  243.  *            2-3        last mail message
  244.  *            4-6        last message read
  245.  */
  246.  
  247. get_mailstate(user, x)
  248. {
  249.     local i, j;
  250.     
  251.     lock(1);
  252.     sprintf(Tmp2, "%smail:%s:control", Directory, user);
  253.     ftmp = fopen(Tmp2, "r+");
  254.     if (ftmp) {
  255.         i = fread(MailState, 6, 1, ftmp);
  256.         if (i != 1 || !x) {
  257.             fclose(ftmp);
  258.         }
  259.         if (i != 1)
  260.             i = -1;
  261.     } else {
  262.         i = 0;
  263.     }
  264.     if (i != 1 || !x)
  265.         unlock(1);
  266.     return(i);
  267. }
  268.  
  269. set_mailstate(user, x)
  270. {
  271.     if (!x) {
  272.         lock(1);
  273.         sprintf(Tmp2, "%smail:%s:control", Directory, user);
  274.         ftmp = fopen(Tmp2, "r+");
  275.     }
  276.     if (ftmp) {
  277.         fseek(ftmp, 0, 0);
  278.         fwrite(MailState, 6, 1, ftmp);
  279.         fclose(ftmp);
  280.     }
  281.     if (x != 2)
  282.         unlock(1);
  283. }
  284.  
  285. delete_mail(first, this, last)
  286. {
  287.     sprintf(Tmp2, "%smail:%s:%d", Directory, User, this);
  288.     remove(Tmp2);
  289.     if (this == first) {
  290.         for (;;) {
  291.             first++;
  292.             if (first > last)
  293.                 break;
  294.             sprintf(Tmp2, "%smail:%s:%d", Directory, User, first);
  295.             ftmp = fopen(Tmp2, "r");
  296.             if (ftmp) {
  297.                 fclose(ftmp);
  298.                 break;
  299.             }
  300.         }
  301.     }
  302.     return(first);
  303. }
  304.  
  305. reply_mail(this)
  306. {
  307.     local i, m, c;
  308.     
  309.     sprintf(Tmp2, "%smail:%s:%d", Directory, User, this);
  310.     ftmp = fopen(Tmp2, "r");
  311.     if (ftmp == NULL) {
  312.         printf("No message %d to reply to\n", this);
  313.         return;
  314.     }
  315.     for (;;) {
  316.         c = fgetc(ftmp);
  317.         if (c == '\'' || c == '\r' || c <= 0)
  318.             break;
  319.     }
  320.     if (c == '\'') {
  321.         for (i = 0;;i++) {
  322.             c = fgetc(ftmp);
  323.             if (c == '\'' || c == '\r' || c <= 0)
  324.                 break;
  325.             XUser[i] = c;
  326.         }
  327.         XUser[i] = 0;
  328.         if (i == 0)
  329.             c = -1;
  330.     }
  331.     if (c == '\'') {
  332.         for (;;) {
  333.             c = fgetc(ftmp);
  334.             if (c == '\'' || c == '\r' || c <= 0)
  335.                 break;
  336.         }
  337.     }
  338.     if (c == '\'') {
  339.         for (i = 0;;i++) {
  340.             c = fgetc(ftmp);
  341.             if (c == '\'' || c == '\r' || c <= 0)
  342.                 break;
  343.             Subject[i] = c;
  344.         }
  345.         Subject[i] = 0;
  346.         if (i == 0)
  347.             c = -1;
  348.     }
  349.     if (c == '\'') {
  350.         for (;;) {
  351.             c = fgetc(ftmp);
  352.             if (c == '\r' || c <= 0)
  353.                 break;
  354.         }
  355.         m = edit_load(ftmp);
  356.         fclose(ftmp);
  357.         if (Subject[0] != 'R' ||
  358.             Subject[1] != 'e' ||
  359.             Subject[2] != ':') {
  360.             strcpy(Tmp1, "Re: ");
  361.         } else {
  362.             Tmp1[0] = 0;
  363.         }
  364.         strcat(Tmp1, Subject);
  365.         strcpy(Tmp2, XUser);
  366.         smail(Tmp2, Tmp1, m);
  367.     } else {
  368.         printf("Malformed file header\n");
  369.         fclose(ftmp);
  370.     }
  371. }
  372.  
  373. pr_subjects(s, e)
  374. {
  375.     local i, x, j, c;
  376.     
  377.     for (i = s, x = 0; i <= e; i++){
  378.         sprintf(Tmp2, "%smail:%s:%d", Directory, User, i);
  379.         ftmp = fopen(Tmp2, "r");
  380.         if (ftmp) {
  381.             for (j = 0;j < 126; j++) {
  382.                 Tmp[j] = c = fgetc(ftmp);
  383.                 if (c == '\r' || c < 0)
  384.                     break;
  385.             }
  386.             Tmp[j] = 0;
  387.             fclose(ftmp);
  388.             if (Tmp[0]) {
  389.                 x = 1;
  390.                 if (cantput())
  391.                     return;
  392.                 printf("%d:    %s\n", i, Tmp);
  393.             }
  394.         }
  395.     }
  396.     if (x == 0)
  397.         printf("No mail found\n");
  398. }
  399.  
  400. display_mail(this)
  401. {
  402.     sprintf(Tmp2, "%smail:%s:%d", Directory, User, this);
  403.     ftmp = fopen(Tmp2, "r");
  404.     if (ftmp == NULL) {
  405.         printf("No mail %d (deleted)\n", this);
  406.         return;
  407.     }
  408.     file_cat(ftmp);
  409.     fclose(ftmp);
  410. }
  411.  
  412. /*
  413.  *     send mail
  414.  */
  415.  
  416. smail(to, subject, xf)
  417. {
  418.     local m, i, x, c, s, done;
  419.     
  420.     if (to == 0) {
  421.         printf("To> ");
  422.         if (readlinetime(XUser, 40, timeout) != 0)
  423.             return;
  424.     } else {
  425.         strcpy(XUser, to);
  426.     }
  427.     if (XUser[0] == 0)
  428.         return;
  429.     if (subject == 0) {
  430.         printf("Subject> ");
  431.         if (readlinetime(Subject, 80, timeout) != 0)
  432.             return;
  433.     } else {
  434.         strcpy(Subject, subject);
  435.     }
  436.     if (xf) {
  437.         m = xf;
  438.     } else {
  439.         m = edit_empty(1);
  440.         if (m == NULL) {
  441.             printf("Cannot open temporary file for editing\n");
  442.             return;
  443.         }
  444.     }
  445.     done = 0;
  446.     for (c = 'e';;) {
  447.         switch(c) {
  448.         case 'h':
  449.         case 'H':
  450.             printf("To> ");
  451.             if (readlinetime(XUser, 40, timeout) != 0) {
  452.                 done = 1;
  453.                 break;
  454.             }
  455.             printf("Subject> ");
  456.             if (readlinetime(Subject, 80, timeout) != 0) {
  457.                 done = 1;
  458.                 break;
  459.             }
  460.             break;
  461.             
  462.         case 'e':
  463.         case 'E':
  464.             edit(m);
  465.             break;
  466.             
  467.         case 's':
  468.         case 'S':
  469.             i = 0;
  470.             x = 0;
  471.             s = 0;
  472.             done = 1;
  473.             for (;c!= 0;i++) {
  474.                 c = XUser[i];
  475.                 if (s == 0) {
  476.                     if (c == 0)
  477.                         break;
  478.                     if (c != ' ' && c != ',') {
  479.                         Tmp1[x++] = c;
  480.                         s = 1;
  481.                     }
  482.                 } else {
  483.                     if (c == 0 || c == ',') {
  484.                         while (x > 0 && Tmp1[x-1] == ' ')
  485.                             x--;
  486.                         if (x != 0) {
  487.                             Tmp1[x] = 0;
  488.                             if (send_mail(Tmp1, Subject, m)) {
  489.                                 printf("Can't send mail to %s\n", Tmp1);
  490.                                 done = 0;
  491.                             } else {
  492.                                 printf("Sent to %s\n", Tmp1);
  493.                             }
  494.                             x = 0;
  495.                         }
  496.                         s = 0;
  497.                     } else {
  498.                         Tmp1[x++] = c;
  499.                     }
  500.                 }
  501.             }
  502.             break;
  503.             
  504.         case 'a':
  505.         case 'A':
  506.             done = 1;
  507.             break;
  508.         }
  509.         if (done)
  510.             break;
  511.         stty('e', 0);
  512.         stty('l', 0);
  513.         printf("Send Mail: A(bort) E(dit mail) H(eader) S(end mail) > ");
  514.         c = getchartime(timeout);
  515.         stty('e', 1);
  516.         stty('l', 1);
  517.         if (c == -2)
  518.             break;
  519.         putchar(c);
  520.         putchar('\n');
  521.     }
  522.     fclose(m);
  523.     if (m == fedit) {
  524.         if (TmpName[0]) {
  525.             remove(TmpName);
  526.             TmpName[0] = 0;
  527.         }
  528.     }
  529.  
  530. }
  531.  
  532. send_mail(to, subject, f)
  533. {
  534.     local last, i;
  535.     
  536.     i = get_mailstate(to, 1);
  537.     if (i != 1) {
  538.         lock(1);
  539.         ftmp = fopen(Tmp2, "w+");
  540.         if (ftmp == NULL) {
  541.             unlock(1);
  542.             return(1);
  543.         }
  544.         last = -1;
  545.         MailState[4] = 0;    
  546.         MailState[5] = 1;
  547.     } else {
  548.         last  = (MailState[2]<<8)|MailState[3];
  549.     }
  550.     if (last == -1) {    /* no mail at all */
  551.         MailState[1] = 1;
  552.         MailState[3] = 0;
  553.         last = 1;
  554.     } else {
  555.         last++;
  556.         MailState[2] = last>>8;
  557.         MailState[3] = last;
  558.     }
  559.     set_mailstate(to, 2);
  560.     sprintf(Tmp2, "%smail:%s:%d", Directory, to, last);
  561.     ftmp = fopen(Tmp2, "w+");
  562.     if (ftmp == NULL) {
  563.         unlock(1);
  564.         return(1);
  565.     }
  566.     fprintf(ftmp, "From: '%s' Subject: '%s'\r", User, subject);
  567.     edit_save(f, ftmp);
  568.     fclose(ftmp);
  569.     unlock(1);
  570.     return(0);
  571. }
  572.  
  573. /*
  574.  *    This routine logs a user on, the user file record will be
  575.  *        in global array 'E'
  576.  *
  577.  */
  578.  
  579. login()
  580. {
  581.     local c, done, try, passwd;
  582.     
  583.     done = 0;
  584.     for (try = 0;try < 3;try++) {
  585.         switch(try) {
  586.         case 0: 
  587.             stty('s', 2400);
  588.             break;
  589.         case 1: 
  590.             stty('s', 1200);
  591.             break;
  592.         case 2: 
  593.             stty('s', 300);
  594.             break;
  595.         }
  596.         for (;;) {
  597.             printf("\nLogin to BBS:");
  598.             if (readlinetime(User, 40, timeout) != 0)
  599.                 break;
  600.             if (User[0] == 0)
  601.                 continue;
  602.             passwd = get_password("Password:", 1);
  603.             if (passwd == 0)
  604.                 break;
  605.             if (userinfo(User, passwd, 0, 0, 0)) {
  606.                 sysop = strcmp("sysop", User) == 0;
  607.                 return(1);
  608.             }
  609.         }
  610.     }
  611.     return(0);
  612. }
  613.  
  614. /*
  615.  *    edit - edits a file (be it empty or otherwise
  616.  *
  617.  *            a VERY simple text editor,
  618.  *
  619.  *        Commands:
  620.  *                    <char>         insert a printable char
  621.  *                    DEL            delete the letter to the left of the cursor (if there is one)
  622.  *                                or join 2 lines
  623.  *                    CR            insert a new line (split an existing one)
  624.  *                    ESC [ A        cursor up
  625.  *                    ESC O A        
  626.  *                    ESC    A
  627.  *                    ESC [ B        cursor down
  628.  *                    ESC O B        
  629.  *                    ESC B        
  630.  *                    ESC [ C        cursor left
  631.  *                    ESC O C        
  632.  *                    ESC C        
  633.  *                    ESC [ D        cursor right
  634.  *                    ESC O D        
  635.  *                    ESC D        
  636.  *                    ^L            refresh
  637.  *                    ^D            Quit
  638.  */
  639.  
  640. edit(f)
  641. {
  642.     local cmd, i, len, b, x, k, j, xcol, tab, wait;
  643.  
  644.     pos = 0;
  645.     col = 0;
  646.     line = 0;
  647.     xcol = 0;
  648.     tab = 0;
  649.     wait = 0;
  650.     stty('e', 0);
  651.     stty('l', 0);
  652.     x = 0;
  653.     for (i = 0; i < 23; i++) {
  654.         if (i < lcount) {
  655.             fseek(f, Map[i]*80, 0);
  656.             fread(&screen[x], 80, 1, f);
  657.         } else {
  658.             screen[x] = 0;
  659.         }
  660.         lmod[i] = 0;
  661.         x += 80;
  662.     }
  663.     lineoffset = 0;
  664.     len = strlen(&screen[0]);
  665.     refresh(f);
  666.     for (;;) {
  667.         if (tab > 0) {
  668.             i = 0;
  669.             nextc = ' ';
  670.             tab--;
  671.         } else {
  672.             i = edit_command();
  673.             if (wait) {
  674.                 refresh();
  675.                 wait = 0;
  676.                 continue;
  677.             }
  678.         }
  679.         switch(i) {
  680.         case 0:        /* insert nextc */
  681.             if (len >= 79) {
  682.                 putchar(7);
  683.                 break;
  684.             }
  685.             xcol = 0;
  686.             lmod[line] = lmod[line]|1;
  687.             if (col == len) {
  688.                 screen[lineoffset+col] = nextc;
  689.                 col++;
  690.                 len++;
  691.                 screen[lineoffset+col] = 0;
  692.                 putchar(nextc);
  693.                 break;
  694.             }
  695.             for (i = (lineoffset+len);i > (lineoffset+col);i--)
  696.                 screen[i] = screen[i-1];
  697.             screen[lineoffset+col] = nextc;
  698.             len++;
  699.             screen[lineoffset+len] = 0;
  700.             putstr(&screen[lineoffset+col]);
  701.             col++;
  702.             goto(col, line);
  703.             break;
  704.             
  705.         case 1:        /* up cursor */
  706.             if (line > 0) {
  707.                 line--;
  708.                 lineoffset -= 80;
  709.                 len = strlen(&screen[lineoffset]);
  710.             } else {
  711.                 if (pos == 0)
  712.                     break;
  713.                 edit_purge(f, 22, 22);
  714.                 for (i = 22, j=(22*80);i > 0; i--, j -= 80) {
  715.                     lmod[i] = lmod[i-1];
  716.                     strcpy(&screen[j], &screen[j-80]);
  717.                 }
  718.                 scroll_down(0, 22);
  719.                 goto(0,0);
  720.                 fseek(f, Map[pos-1]*80, 0);
  721.                 fread(&screen[0], 80, 1, f);
  722.                 putstr(&screen[0]);
  723.                 lmod[0] = 0;
  724.             }
  725.             pos--;
  726.             if (xcol && col < xcol)
  727.                 col = xcol;
  728.             if (col > len) {
  729.                 xcol = col;
  730.                 col = len;
  731.             }
  732.             goto(col, line);
  733.             break;
  734.             
  735.         case 2:
  736.             if (pos == (lcount-1))
  737.                 break;
  738.             if (line < 22) {
  739.                 line++;
  740.                 lineoffset += 80;
  741.                 len = strlen(&screen[lineoffset]);
  742.             } else {
  743.                 edit_purge(f, 0, 0);
  744.                 for (i = 0, j=0;i < 22; i++, j += 80) {
  745.                     lmod[i] = lmod[i+1];
  746.                     strcpy(&screen[j], &screen[j+80]);
  747.                 }
  748.                 scroll_up(0, 22);
  749.                 goto(0,22);
  750.                 fseek(f, Map[pos+1]*80, 0);
  751.                 x=fread(&screen[lineoffset], 80, 1, f);
  752.                 putstr(&screen[lineoffset]);
  753.                 lmod[22] = 0;
  754.             }
  755.             pos++;
  756.             if (xcol && col < xcol)
  757.                 col = xcol;
  758.             if (col > len) {
  759.                 xcol = col;
  760.                 col = len;
  761.             }
  762.             goto(col, line);
  763.             break;
  764.             
  765.         case 3:
  766.             if (col < len) {
  767.                 col++;
  768.                 xcol = 0;
  769.             }
  770.             goto(col, line);
  771.             break;
  772.             
  773.         case 4:
  774.             if (col > 0) {
  775.                 col--;
  776.                 xcol = 0;
  777.             }
  778.             goto(col, line);
  779.             break;
  780.             
  781.         case 5:
  782.             refresh(f);
  783.             break;
  784.             
  785.         case 6:
  786.             clear();
  787.             edit_purge(f, 0, 22);
  788.             stty('e', 1);
  789.             stty('l', 1);
  790.             return;
  791.             
  792.         case 7:
  793.             if (col == 0) {
  794.                 if (pos == 0)
  795.                     break;
  796.                 if (line == 0) {
  797.                     fseek(f, Map[pos-1]*80, 0);
  798.                     fread(Tmp, 80, 1, f);
  799.                     i = strlen(Tmp);
  800.                     if ((i + len) > 79) {    /* too long */
  801.                         putchar('\007');
  802.                         break;
  803.                     }
  804.                     strcpy(&Tmp[i], &screen[0]);
  805.                     strcpy(&screen[0], Tmp);
  806.                     len += i;
  807.                     edit_freeblock(Map[pos]);
  808.                     col = i;
  809.                     lcount--;
  810.                     for (i = pos; i < lcount; i++)
  811.                         Map[i] = Map[i+1];
  812.                     pos--;
  813.                     goto(0, 0);
  814.                     putstr(&screen[0]);
  815.                 } else {
  816.                     i = strlen(&screen[lineoffset-80]);
  817.                     if ((i+len) > 79) {
  818.                         putchar('\007');
  819.                         break;
  820.                     }
  821.                     col = i;
  822.                     goto(col, line-1);
  823.                     putstr(&screen[lineoffset]);
  824.                     strcpy(&screen[lineoffset-80+i], &screen[lineoffset]);
  825.                     for (i = line, j = pos, k = lineoffset; i < 22; i++, j++, k += 80) {
  826.                         if (j > lcount)
  827.                             break;
  828.                         strcpy(&screen[k], &screen[k+80]);
  829.                     }
  830.                     len += col;
  831.                     edit_freeblock(Map[pos]);
  832.                     lcount--;
  833.                     for (i = pos; i < lcount; i++)
  834.                         Map[i] = Map[i+1];
  835.                     for (i = line; i < 22; i++)
  836.                         lmod[i] = lmod[i+1];
  837.                     pos--;
  838.                     scroll_up(line, 22);
  839.                     i = pos-line+22;
  840.                     if (i >= lcount) {
  841.                         goto(0, 22);
  842.                         putchar('~');
  843.                         screen[80*22] = 0;
  844.                     } else {
  845.                         fseek(f, Map[i]*80, 0);
  846.                         fread(&screen[80*22], 80, 1, f);
  847.                         goto(0, 22);
  848.                         putstr(&screen[80*22]);
  849.                         lmod[22] = 0;
  850.                     }
  851.                     line--;
  852.                     lineoffset -= 80;
  853.                 }
  854.                 goto(col, line);
  855.                 lmod[line] = lmod[line]|1;
  856.                 break;
  857.             }
  858.             xcol = 0;
  859.             col--;
  860.             len--;
  861.             lmod[line] = lmod[line]|1;
  862.             if (col == len) {
  863.                 screen[lineoffset+len] = 0;
  864.                 goto(col, line);
  865.                 putchar(' ');
  866.                 goto(col, line);
  867.                 break;
  868.             }
  869.             goto(col, line);
  870.             putstr(&screen[lineoffset+col+1]);
  871.             putchar(' ');
  872.             goto(col, line);
  873.             for (i = (lineoffset+col); i < (lineoffset+len); i++)
  874.                 screen[i] = screen[i+1];
  875.             screen[lineoffset+len] = 0;
  876.             break;
  877.             
  878.         case 8:
  879.             b = edit_newblock(f, 0);
  880.             xcol = 0;
  881.             if (col != len)
  882.                 erase_eol();
  883.             if (line == 22) {
  884.                 edit_purge(f, 0, 0);
  885.                 x = screen[lineoffset+col];
  886.                 screen[lineoffset+col] = 0;
  887.                 for (i = 0, j = 0;i < 22; i++, j += 80) {
  888.                     lmod[i] = lmod[i+1];
  889.                     strcpy(&screen[j], &screen[j+80]);
  890.                 }
  891.                 screen[lineoffset+col] = x;
  892.                 strcpy(&screen[lineoffset], &screen[lineoffset+col]); 
  893.                 if (len != col)
  894.                     lmod[21] = lmod[21]|1;
  895.             } else {
  896.                 edit_purge(f, 22, 22);
  897.                 for (i = 22, j=(22*80);i > (line+1); i--, j -= 80) {
  898.                     lmod[i] = lmod[i-1];
  899.                     strcpy(&screen[j], &screen[j-80]);
  900.                 }
  901.                 strcpy(&screen[lineoffset+80], &screen[lineoffset+col]); 
  902.                 screen[lineoffset+col] = 0;
  903.                 if (len != col)
  904.                     lmod[line] = lmod[line]|1;
  905.             }
  906.             len -= col;
  907.             col = 0;
  908.             pos++;
  909.             for (i = lcount; i > pos; i--)
  910.                 Map[i] = Map[i-1];
  911.             lcount++;
  912.             Map[pos] = b;
  913.             if (line == 22) {            /* scroll everything up */
  914.                 scroll_up(0, 22);
  915.             } else {
  916.                 line++;
  917.                 lineoffset += 80;
  918.                 scroll_down(line, 22);
  919.             }
  920.             lmod[line] = lmod[line]|1;
  921.             goto(0, line);
  922.             if (col != len) {
  923.                 putstr(&screen[lineoffset]);
  924.                 goto(0, line);
  925.             }
  926.             break;
  927.  
  928.         case 9:
  929.             i = col&7;
  930.             if (i == 0) {
  931.                 tab = 8;
  932.             } else {
  933.                 tab = 8 - i;
  934.             }
  935.             break;
  936.             
  937.         case 10:
  938.             clear();     putstr("Taniwha BBS Editor");
  939.             goto(0, 1);     putstr("==================");
  940.             goto(0, 3);     putstr("Type any character to insert it at the cursor");
  941.             goto(0, 5);     putstr("Type type the 'Delete' or 'Backspace' key to delete the character");
  942.             goto(0, 6);     putstr("    to the left off the cursor, or, if the cursor is at the left");
  943.             goto(0, 7);     putstr("    of the screen to join the current line to the previous one.");
  944.             goto(0, 9);     putstr("Type 'return' to insert a new line at the cursor");
  945.             goto(0, 11); putstr("Use the arrow keys to move on the screen (or 'ESC' A/B/C/D to");
  946.             goto(0, 12); putstr("    move up/down/left right)");
  947.             goto(0, 14); putstr("Type Ctrl-D (hold down the 'Control' key and type D)");
  948.             goto(0, 15); putstr("    to exit the editor)");
  949.             goto(0, 22); putstr("Type any character to continue");
  950.             wait = 1;
  951.             break;
  952.         }
  953.     }
  954. }
  955.  
  956. /*
  957.  *    write back the changed lines to the backing store 
  958.  */
  959.  
  960. edit_purge(f, s, e)
  961. {
  962.     local i, x;
  963.     
  964.     for (i = s; i <= e; i++)
  965.     if (lmod[i]) {
  966.         x = pos-line+i;
  967.         if (x >= lcount)
  968.             break;
  969.         fseek(f, Map[x]*80, 0);
  970.         fwrite(&screen[i*80], 80, 1, f);
  971.     }
  972. }
  973.  
  974. /*
  975.  *    append the edit file f to f2
  976.  */
  977.  
  978. edit_save(f, f2)
  979. {
  980.     local i, j;
  981.     
  982.     for (i = 0; i < lcount; i++) {
  983.         fseek(f, Map[i]*80, 0);
  984.         fread(Tmp, 80, 1, f);
  985.         j = strlen(Tmp);
  986.         Tmp[j] = '\r';
  987.         fwrite(Tmp, j+1, 1, f2);
  988.     }
  989. }
  990.  
  991. /*
  992.  *    make a new edit file containing the contents of the rest of file f
  993.  */
  994.  
  995. edit_load(f)
  996. {
  997.     local m;
  998.     
  999.     m = edit_empty(0);
  1000.     if (m == NULL) {
  1001.         return(NULL);
  1002.     }
  1003.     edit_append(m, f);
  1004.     return(m);
  1005. }
  1006.  
  1007. /*
  1008.  *    load the rest of file f into edit file m
  1009.  */
  1010.  
  1011. edit_append(m, f)
  1012. {
  1013.     local l, x, i, c;
  1014.     
  1015.     l = 0;
  1016.     x = 0;
  1017.     i = 0;
  1018.     for (;;) {
  1019.         if (l == i) {
  1020.             l = fread(Tmp2, 1, 128, f);
  1021.             if (l <= 0)
  1022.                 break;
  1023.             i = 0;
  1024.         }
  1025.         c = Tmp2[i];
  1026.         i++;
  1027.         if (c == '\r') {
  1028.             Tmp1[x] = 0;
  1029.             x = 0;
  1030.             Map[lcount] = edit_newblock(m, 1);
  1031.             fseek(m, 80*Map[lcount], 0);
  1032.             fwrite(Tmp1, 80, 1, m);
  1033.             lcount++;
  1034.             if (lcount == MAPSIZE)
  1035.                 break;
  1036.         } else {
  1037.             if (x < 79) {
  1038.                 Tmp1[x] = c;
  1039.                 x++;
  1040.             }
  1041.         }
  1042.     }
  1043.     if (x > 0 || lcount == 0) {
  1044.         Tmp1[x] = 0;
  1045.         Map[lcount] = edit_newblock(m, 1);
  1046.         fseek(m, 80*Map[lcount], 0);
  1047.         fwrite(Tmp1, 80, 1, m);
  1048.         lcount++;
  1049.     }
  1050. }
  1051.  
  1052. /*
  1053.  *    make a temporary edit file
  1054.  */
  1055.  
  1056. edit_empty(add)
  1057. {
  1058.     local i;
  1059.     
  1060.     A++;
  1061.     i = A;            /* use global variable to get unique file name */
  1062.     sprintf(TmpName, "%stmp:%d", Directory, i);
  1063.     fedit = fopen(TmpName, "w+");
  1064.     if (fedit == NULL)
  1065.         return(NULL);
  1066.     elist = 0;
  1067.     efree = 0;
  1068.     if (add) {
  1069.         Map[0] = edit_newblock(fedit, 1);
  1070.         Tmp[0] = 0;
  1071.         fseek(fedit, Map[0]*80, 0);
  1072.         fwrite(Tmp, 80, 1, fedit);    /* add an empty line */
  1073.         lcount = 1;
  1074.     } else {
  1075.         lcount = 0;
  1076.     }
  1077.     return(fedit);
  1078. }
  1079.  
  1080. /*
  1081.  *    what follows are for a vt100, change to suit your own terminal(s)
  1082.  */
  1083.  
  1084. /*
  1085.  *    scroll up 1 line the screen between lines t(op) and b(ottom)
  1086.  */
  1087.  
  1088. scroll_up(t, b)
  1089. {
  1090.     set_scroll(t, b);
  1091.     goto(0, b);
  1092.     putchar('\n');
  1093.     clear_scroll();
  1094. }
  1095.  
  1096. /*
  1097.  *    scroll down 1 line the screen between lines t(op) and b(ottom)
  1098.  */
  1099.  
  1100. scroll_down(t, b)
  1101. {
  1102.     set_scroll(t, b);
  1103.     goto(0, t);
  1104.     putstr("\033M");
  1105.     clear_scroll();
  1106. }
  1107.  
  1108. /*
  1109.  *    put the screen into scroll mode between lines t and b
  1110.  */
  1111.  
  1112. set_scroll(t, b)
  1113. {
  1114.     printf("\033[%d;%dr", t+1,b+1);
  1115. }
  1116.  
  1117. /*
  1118.  *    clear scrolling region
  1119.  */
  1120.  
  1121. clear_scroll()
  1122. {
  1123.     putstr("\033[r");
  1124. }
  1125.  
  1126. /*
  1127.  *    erase the line from the cursor to the end
  1128.  */
  1129.  
  1130. erase_eol()
  1131. {
  1132.     putstr("\033[K");
  1133. }
  1134.  
  1135. /*
  1136.  *    clear the whole screen
  1137.  */
  1138.  
  1139. clear()
  1140. {
  1141.     putstr("\033[H\033[J");
  1142. }
  1143.  
  1144. /*
  1145.  *    go to a particular screen location
  1146.  */
  1147.  
  1148. goto(x, y)
  1149. {
  1150.     printf("\033[%d;%dH",y+1,x+1);
  1151. }
  1152.  
  1153. /*
  1154.  *    redraw the screen
  1155.  */
  1156.  
  1157. refresh(f)
  1158. {
  1159.     local i, j;
  1160.     
  1161.     clear_scroll();
  1162.     clear();
  1163.     for (i = 0, j = 0; i < 23; i++, j += 80) {
  1164.         goto(0, i);
  1165.         if ((pos-line+i) < lcount) {
  1166.             putstr(&screen[j]);
  1167.         } else {
  1168.             putchar('~');
  1169.         }
  1170.     }
  1171.     goto(0, 23);
  1172.     putstr("^D - quit, DEL delete, ^L refresh - use arrows to move, <ESC> ? for help");
  1173.     goto(col, line);
  1174. }
  1175.  
  1176. cantput()
  1177. {
  1178.     local x, y;
  1179.     
  1180.     y = 1;
  1181.     resched();
  1182.     resched();
  1183.     x = peekc();
  1184.     for (;;) {
  1185.         if (y && x < 0)
  1186.             return(0);
  1187.         x = getchar();
  1188.         if (x == 's' || x == 'S' || x == 0x13) {
  1189.             x = getchar();
  1190.             y = 0;
  1191.             continue;
  1192.         }
  1193.         if (x == 'q' || x == 'Q' || x == 0x11)
  1194.             return(0);
  1195.         if (x == 3 || x == 'k' || x == 'K')
  1196.             return(1);
  1197.     }
  1198. }
  1199.  
  1200. /*
  1201.  *    allocate an 80 byte block from the file
  1202.  */
  1203.  
  1204. edit_newblock(f, a)
  1205. {
  1206.     local x;
  1207.     
  1208.     if (elist) {
  1209.         x = elist;
  1210.         fseek(f, elist*80, 0);
  1211.         fread(Tmp, 80, 1, f);
  1212.         elist = Tmp[0];
  1213.         return(x);
  1214.     }
  1215.     x = efree;
  1216.     if (a == 0) {
  1217.         fseek(f, efree*80, 0);
  1218.         fwrite(Tmp, 80, 1, f);
  1219.     }
  1220.     efree++;
  1221.     return(x);
  1222. }
  1223.  
  1224. /*
  1225.  *    free a block from the file
  1226.  */
  1227.  
  1228. edit_freeblock(f, x)
  1229. {
  1230.     local x;
  1231.     
  1232.     if (x == (efree-1)) {
  1233.         efree = x;
  1234.         return;
  1235.     }
  1236.     Tmp[0] = elist;
  1237.     fseek(f, x*80, 0);
  1238.     fwrite(Tmp, 80, 1, f);
  1239.     elist = x;
  1240. }
  1241.  
  1242. /*
  1243.  * edit commands, returned in d:
  1244.  *
  1245.  *            0    - insert char
  1246.  *            1    - up
  1247.  *            2      - down
  1248.  *            3      - left
  1249.  *            4      - right
  1250.  *            5      - refresh
  1251.  *            6      - quit
  1252.  *            7    - delete
  1253.  *            8    - new line
  1254.  *            9    - tab
  1255.  *            10    - help
  1256.  */
  1257.  
  1258. edit_command()
  1259. {
  1260.     local d;
  1261.     
  1262.     d = 0;
  1263.     for (;;) {
  1264.         nextc = getchartime(timeout);
  1265.         if (nextc == -2)
  1266.             return(6);
  1267.         switch(d) {
  1268.         case 0:
  1269.             if (nextc >= ' ' && nextc < 0x7f)
  1270.                 return(0);
  1271.             if (nextc == '\033') {
  1272.                 d = 1;
  1273.                 continue;
  1274.             }
  1275.             if (nextc == 9) {
  1276.                 return(9);
  1277.             }
  1278.             if (nextc == 0x7f || nextc == 8) {
  1279.                 return(7);
  1280.             }
  1281.             if (nextc == 13 || nextc == 11)
  1282.                 return(8);
  1283.             if (nextc == 4)
  1284.                 return(6);
  1285.             if (nextc == 12)
  1286.                 return(5);
  1287.             break;
  1288.             
  1289.         case 1:
  1290.             if (nextc == '?')
  1291.                 return(10);
  1292.             if (nextc == 'O' || nextc == '[') {
  1293.                 d = 2;
  1294.                 continue;
  1295.             }
  1296.         case 2:
  1297.             if (nextc >= 'A' && nextc <= 'D')
  1298.                 return(nextc - 'A' + 1);
  1299.             if (nextc >= 'a' && nextc <= 'd')
  1300.                 return(nextc - 'a' + 1);
  1301.             d = 0;
  1302.             break;
  1303.         }
  1304.     }
  1305. }
  1306.  
  1307. /*
  1308.  *    This routine takes the user name in global array A
  1309.  *        and a 16-bit hashed password in global variable a
  1310.  *        it locks updates between multiple users.
  1311.  *
  1312.  *    If add is set then an entry is also added
  1313.  *
  1314.  *    If del is set and a==0 or a==the password in the entry
  1315.  *        the entry is deleted
  1316.  *
  1317.  *    If pass is set then set the password
  1318.  *
  1319.  */
  1320.  
  1321. userinfo(name, passwd, add, del, pass)
  1322. {
  1323.     local r, i, c;
  1324.     
  1325.     passwd &= 0xffff;
  1326.     r = 0;
  1327.     i = -1;
  1328.     sprintf(Tmp, "%scontrol:User File", Directory);
  1329.     lock(0);                /* lock the user data base */
  1330.     fuser = fopen(Tmp, "r+");
  1331.     if (fuser == NULL) {
  1332.         fuser = fopen(Tmp, "w");
  1333.         if (fuser == NULL) {
  1334.             sprintf(Tmp, "%scontrol", Directory);
  1335.             mkdir(Tmp);
  1336.             sprintf(Tmp, "%scontrol:User File", Directory);
  1337.             fuser = fopen(Tmp, "w");
  1338.             if (fuser == NULL) {
  1339.                 unlock(0);
  1340.                 return(0);
  1341.             }
  1342.         }
  1343.         strcpy(Tmp, "sysop");
  1344.         Tmp[38] = 0;
  1345.         Tmp[39] = 1;
  1346.         fwrite(Tmp, 40, 1, fuser);
  1347.         strcpy(Tmp, "guest");
  1348.         Tmp[38] = 0;
  1349.         Tmp[39] = 1;
  1350.         fwrite(Tmp, 40, 1, fuser);
  1351.         fclose(fuser);
  1352.         sprintf(Tmp, "%smail", Directory);
  1353.         mkdir(Tmp);
  1354.         sprintf(Tmp, "%smail:sysop", Directory);
  1355.         mkdir(Tmp);
  1356.         sprintf(Tmp, "%smail:guest", Directory);
  1357.         mkdir(Tmp);
  1358.         sprintf(Tmp, "%scontrol:User File", Directory);
  1359.         fuser = fopen(Tmp, "r+");
  1360.     }
  1361.     if (fuser) {
  1362.         for (;;) {
  1363.             i = fread(Tmp, 40, 1, fuser);
  1364.             if (i <= 0) {
  1365.                 if (add) {
  1366.                     name[38] = passwd>>8;
  1367.                     name[39] = passwd;
  1368.                     if (r != 0) {
  1369.                         fseek(fuser, r-40, 0);
  1370.                     } else {
  1371.                         fseek(fuser, 0, 2);
  1372.                     }
  1373.                     fwrite(name, 40, 1, fuser);
  1374.                     memcpy(UserRecord, name, 40);
  1375.                     r = 1;
  1376.                 } else {
  1377.                     r = 0;
  1378.                 }
  1379.                 fclose(fuser);
  1380.                 unlock(0);
  1381.                 return(r);
  1382.             }
  1383.             if (Tmp[0] == 0) {
  1384.                 if (r == 0)
  1385.                     r = ftell(fuser);
  1386.             } else 
  1387.             if (strcmp(Tmp, name) == 0) {
  1388.                 c = (Tmp[38]<<8)|Tmp[39];
  1389.                 if (pass || (del && (passwd == 0 || passwd == c || sysop))) {
  1390.                     if (del) {
  1391.                         Tmp[0] = 0;
  1392.                     } else
  1393.                     if (pass) {
  1394.                         Tmp[38] = passwd>>8;
  1395.                         Tmp[39] = passwd;
  1396.                     }
  1397.                     fseek(fuser, -40, 1);
  1398.                     fwrite(Tmp, 40, 1, fuser);
  1399.                 }
  1400.                 memcpy(UserRecord, Tmp, 40);
  1401.                 fclose(fuser);
  1402.                 unlock(0);
  1403.                 return(pass || passwd == c || passwd == 0 || sysop);
  1404.             }
  1405.         }
  1406.     }
  1407.     unlock(0);
  1408.     return(0);
  1409. }
  1410.  
  1411. /*
  1412.  *    print the contents of a file
  1413.  */
  1414.  
  1415. file_cat(f)
  1416. {
  1417.     local i, l;
  1418.  
  1419.     for (;;) {
  1420.         if (cantput())
  1421.             break;
  1422.         l = fread(Tmp, 1, 128, f);
  1423.         if (l <= 0)
  1424.             break;
  1425.         for (i = 0; i < l; i++)
  1426.         if (Tmp[i] == '\r')
  1427.             Tmp[i] = '\n';
  1428.         putline(Tmp, l);
  1429.     }
  1430. }
  1431.  
  1432. /*
  1433.  *    print 'message of the day'
  1434.  */
  1435.  
  1436. message_of_the_day()
  1437. {
  1438.     sprintf(Tmp2, "%smessage", Directory);
  1439.     ftmp = fopen(Tmp2, "r");
  1440.     if (ftmp) {
  1441.         file_cat(ftmp);
  1442.         fclose(ftmp);
  1443.     }
  1444. }
  1445.  
  1446.  
  1447. config()
  1448. {
  1449.     local c;
  1450.     
  1451.     for (;;) {
  1452.         stty('e', 0);
  1453.         stty('l', 0);
  1454.         printf("Config: A(dd user) D(elete user) P(assword) Q(uit) > ");
  1455.         c = getchar();
  1456.         stty('e', 1);
  1457.         stty('l', 1);
  1458.         putchar(c);
  1459.         putchar('\n');
  1460.         switch(c) {
  1461.         case 'A':
  1462.         case 'a':
  1463.             printf("Add User: ");
  1464.             readline(XUser, 40);
  1465.             set_password(XUser, 1);
  1466.             sprintf(Tmp, "%smail:%s", Directory, XUser);
  1467.             mkdir(Tmp);
  1468.             break;
  1469.             
  1470.         case 'D':
  1471.         case 'd':
  1472.             printf("Delete User: ");
  1473.             readline(XUser, 40);
  1474.             if (!userinfo(XUser, 0, 0, 1, 0))
  1475.                 printf("Invalid user '%s'\n", XUser);
  1476.             break;
  1477.             
  1478.         case 'P':
  1479.         case 'p':
  1480.             printf("Password User: ");
  1481.             readline(XUser, 40);
  1482.             set_password(XUser, 0);
  1483.             break;
  1484.             
  1485.         case 'Q':
  1486.         case 'q':    
  1487.             return;
  1488.         }
  1489.     }
  1490. }
  1491.  
  1492. set_password(user, add)
  1493. {
  1494.     local i1, i2;
  1495.     i1 = get_password("New Password: ", 0);
  1496.     i2 = get_password("Re-enter new Password: ", 0);
  1497.     if (i1 != i2) {
  1498.         printf("Passwords not the same, try again\n");
  1499.         return;
  1500.     }
  1501.     if (!userinfo(user, i1, add, 0, 1))
  1502.         printf("Invalid user '%s'\n", user);
  1503. }
  1504.  
  1505. get_password(prompt, t)
  1506. {
  1507.     local passwd, done, c;
  1508.     
  1509.     done = 0;
  1510.     stty('e', 0);
  1511.     stty('l', 0);
  1512.     putstr(prompt);
  1513.     passwd = 0;
  1514.     for (;;) {
  1515.         c = getchartime(timeout);
  1516.         if (c == -2)
  1517.             break;
  1518.         if (t && (c&0x80 || c == 0)) 
  1519.             break;
  1520.         if (c == '\n' || c == '\r') {
  1521.             done = 1;
  1522.             break;
  1523.         }
  1524.         passwd = passwd + (c<<1);
  1525.         putchar('.');
  1526.     }
  1527.     stty('e', 1);
  1528.     stty('l', 1);
  1529.     putchar('\n');
  1530.     if (t && !done)
  1531.         return(0);
  1532.     if (passwd == 0)
  1533.         passwd = 1;
  1534.     return(passwd);
  1535. }
  1536.  
  1537. /*
  1538.  * file upload/download area
  1539.  */
  1540.  
  1541. do_files()
  1542. {
  1543.     local c, t, f;
  1544.     
  1545.     f = "XMODEM";
  1546.     t = "Method StraightXMODEM Option Standard Creator \"ttxt\" Timeout 5 Retry 5 RemoteName False";
  1547.     
  1548.     for (;;) {
  1549.         stty('e', 0);
  1550.         stty('l', 0);
  1551.         printf("Files: D(ownload) U(pload) L(ist) Q(uit) > ");
  1552.         c = getchartime(timeout);
  1553.         stty('e', 1);
  1554.         stty('l', 1);
  1555.         if (c == -2)
  1556.             return;
  1557.         putchar(c);
  1558.         putchar('\n');
  1559.         switch(c) {
  1560.         case 'D':
  1561.         case 'd':
  1562.             printf("File> ");
  1563.             if (readlinetime(Tmp, 40, timeout) != 0)
  1564.                 continue;
  1565.             if (Tmp[0] == 0)
  1566.                 continue;
  1567.             sprintf(Tmp2, "%sfiles:%s", Directory, Tmp);
  1568.             ftmp = fopen(Tmp2, "r");
  1569.             if (ftmp == NULL) {
  1570.                 printf("File %s doesn't exist\n", Tmp);
  1571.                 break;
  1572.             }
  1573.             fclose(ftmp);
  1574.             if (ft_new(f, t)) {
  1575.                 printf("Transfer Failed\n");
  1576.                 break;
  1577.             }
  1578.             sprintf(Tmp2, "%sfiles", Directory);
  1579.             if (ft_start(Tmp2, Tmp, 1))
  1580.                 printf("Transfer Failed\n");
  1581.             ft_dispose();
  1582.             break;
  1583.             
  1584.         case 'U':
  1585.         case 'u':
  1586.             printf("File> ");
  1587.             if (readlinetime(Tmp, 40, timeout) != 0)
  1588.                 continue;
  1589.             if (Tmp[0] == 0)
  1590.                 continue;
  1591.             sprintf(Tmp2, "%sfiles:%s", Directory, Tmp);
  1592.             ftmp = fopen(Tmp2, "r");
  1593.             if (ftmp) {
  1594.                 fclose(ftmp);
  1595.                 printf("File %s already exists\n", Tmp);
  1596.                 break;
  1597.             }
  1598.             if (ft_new(f, t)) {
  1599.                 printf("Transfer Failed\n");
  1600.                 break;
  1601.             }
  1602.             sprintf(Tmp2, "%sfiles", Directory);
  1603.             if (ft_start(Tmp2, Tmp, 0))
  1604.                 printf("Transfer Failed\n");
  1605.             ft_dispose();
  1606.             break;
  1607.             
  1608.         case 'L':
  1609.         case 'l':
  1610.             break;
  1611.             
  1612.         case 'Q':
  1613.         case 'q':    
  1614.             return;
  1615.         }
  1616.     }
  1617. }
  1618.  
  1619.